/*
 * Created on Wed Jun 06 2018 by Ronnie Ren (zhaosong.ren) from Accenture
 *
 * Copyright (c) 2018 DingXing information & technology limited company.
 */

import { Injectable } from "@angular/core";
import { SqliteService } from "../../services/sqliteDB/sqlite.service";
import { Observable } from 'rxjs/Observable';
import { WorkOrderDto } from "../dto/work-orders.dto";
import { WorkOrder, WorkOrderStatus, WorkOrderType } from "../transform/work-order";
import { AttachmentService } from "./attachment.service";
import { CurdService } from "./curd.service";
import { SyncUtilService } from "../../services/offline/sync.util.service";
import {JSONMapping} from "../json-mapping";
import {Attachment} from "../transform/attachment";
import {BillDto} from "../dto/bill.dto";
import {SyncStatus} from "../sync-status";
import {Bill} from "../transform/bill";
import {JsonMappingUtil} from "../json-mapping-util";
import {ConditionFetch, ConditionPair} from "../../services/sqliteDB/condition-fetch";

@Injectable()
export class WorkOrderService {

  constructor(
    private sqliteService: SqliteService,
    private attachmentService: AttachmentService,
    private syncUtilService: SyncUtilService,
    private curdService: CurdService
  ) {

  }

  fetchWorkOrderBySyncStatus(syncStatuses: Array<SyncStatus>, count: number = 1): Observable<Array<WorkOrder>> {
    return this.curdService.observableFetchObjectsByPage(
      WorkOrderDto,
      null,
      [{ syncStatus: syncStatuses }]
    )
      .flatMap((workOrders: Array<WorkOrderDto>) => {
        if (!workOrders || workOrders.length < 1) {
          return Observable.of([]);
        }
        else {
          return Observable.combineLatest(
            workOrders.map((workOrderDto) => this.getWorkOrdersAndAttachmentsFromWorkOrders(workOrderDto))
          )
            .map((workOrdersArray) => workOrdersArray.reduce((result, workOrder) => result.concat(workOrder), []));
        }
      });
  }

  fetchWorkOrderByUserId(userId: string): Observable<Array<WorkOrder>> {
    let workDto = new WorkOrderDto;
    let sql = `select * from ${workDto.table().tableName} where userId = '${userId}' `;

    return Observable.fromPromise(
      this.sqliteService.executeSqlWithResults<WorkOrderDto>(sql, WorkOrderDto))
      .map((workOrders: Array<WorkOrderDto>) => {
        return workOrders.map((aDto) => new WorkOrder(aDto));
    });
  }

  fetchInProgressWorkOrderByUserId(userId: string): Observable<Array<WorkOrder>> {
    return this.fetchInProgressWorkOrders(userId, [WorkOrderType.POWERCUT, WorkOrderType.POWERRECOVERY]);
  }

  fetchInProgressWorkOrderByUserIdAndType(userId: string, andWorkOrderType: WorkOrderType): Observable<WorkOrder> {
    return this.fetchInProgressWorkOrders(userId, [andWorkOrderType])
      .map((workOrders) => workOrders.length > 0 ? workOrders[0] : null);
  }

  submitData<T extends Attachment>(paths: Array<T>, data: any, workOrder: WorkOrder) {
    if (paths.length > 0) {
      let pathArray: Array<string> = [];
      paths.forEach((item) => {
        pathArray.push(item.path);
      });
      let attachments = workOrder.addNoticeAttachments(pathArray);
      this.attachmentService.addImg(attachments);
      workOrder.powerCutPhotoIds = attachments.map((item) => item.id).join(",");
      data.powerCutPhotoIds = workOrder.powerCutPhotoIds;
    }

    let workOrderDto = new WorkOrderDto();
    workOrderDto.powerCutPhotoIds = workOrder.powerCutPhotoIds;
    workOrderDto.id = workOrder.id;


    return Observable.fromPromise(this.curdService.update(
      { dto: WorkOrderDto, mapObj: WorkOrder }, data,
      { and: { id: workOrder.id } }));
  }

  submitPowerCutApplication(workOrder: WorkOrder): Observable<boolean> {
    let dto = this.syncUtilService.toObjectDto(workOrder, WorkOrderDto);
    return this.curdService.addRows([dto]);
  }

  getWorkOrderArray(condition: ConditionFetch, orderBy: Array<string> = []): Observable<Array<WorkOrder>> {
    return Observable.fromPromise(this.curdService.fetchByCondition(WorkOrderDto,
      condition, orderBy))
      .map((results) => {
        return Array.from(results["results"]);
      })
      .map((results) => {
        return results.map((row: any) => {
          let workOrderDto: any = new WorkOrderDto();
          JsonMappingUtil.MappingAllProp(row, workOrderDto);
          return workOrderDto;
        });
      });
  }

  private getWorkOrdersAndAttachmentsFromWorkOrders(workOrderDto: WorkOrderDto): Observable<WorkOrder> {
    // let obs = billDtos.map((dto) => {
    let workOrder = new WorkOrder({});
    JsonMappingUtil.MappingAllProp(workOrderDto, workOrder);
    if (workOrder.powerCutPhotoIds) {
      return this.attachmentService.fetchAttachmentByIds(workOrder.powerCutPhotoIds.split(","))
        .do((attachments) => {
          console.log(attachments, "attachments ------");
          workOrder.noticeAttachments = attachments;
          console.log(workOrder, "workOrder ------");
        })
        .map(() => {
          console.log(workOrder);
          return workOrder;
        });
    } else {
      workOrder.noticeAttachments = [];
      return Observable.of(workOrder);
    }

    // return this.attachmentService.fetchAttachmentByIds(dto.attachmentIds.split(","))
    //   .do((attachments) => bill.noticeAttachments = attachments).map(() => bill);
    // });
    // return Observable.combineLatest(obs);
  }

  private fetchInProgressWorkOrders(userId: string, andWorkOrderTypes: Array<WorkOrderType>): Observable<Array<WorkOrder>> {
    let workOrderDto = new WorkOrderDto();
    let finishedOrderStatusList = [WorkOrderStatus.REJECTED, WorkOrderStatus.EXECUTED];
    return Observable.fromPromise(
      this.sqliteService.executeSqlWithResults<WorkOrderDto>(
        `select * from ${workOrderDto.table().tableName} ` +
        `where userId = '${userId}' and ` +
        `(workOrderStatus not in (${finishedOrderStatusList})) and ` +
        ` type in (${andWorkOrderTypes.join(",")})`, WorkOrderDto)
    )
      .map((dtos: Array<WorkOrderDto>) => {
        return dtos.map((dto) => this.syncUtilService.toObjectFromDto(dto, WorkOrder));
      });
  }


}
